package com.qclix.inv.dao;

import com.qclix.inv.Contract;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.sql.SQLException;
import java.util.Calendar;
import java.util.List;

/**
 * @author Pierre Moermans
 */
public class HibernateTemplateContractDaoImpl extends HibernateDaoSupport implements ContractDAO {
    @Override
    @Transactional(propagation = Propagation.SUPPORTS)
    public List<Contract> getAllContracts() {
        return getHibernateTemplate().loadAll(Contract.class);
    }

    private static final String CLIENT_CONTRACTS =
            "select contract from Contract contract where contract.client.id = :clientid";
    @Override
    @Transactional(propagation = Propagation.SUPPORTS)
    public List<Contract> getClientContracts(final long clientId) {
        return (List<Contract>) getHibernateTemplate().execute(new HibernateCallback() {
            public Object doInHibernate(Session session) throws HibernateException, SQLException {
                Query query = getSession().createQuery(CLIENT_CONTRACTS);
                query.setLong("clientid", clientId);
                return query.list();
            }
        });
    }

    private static final String INVOICE_CONTRACT =
            "select i.contract from Invoice i where i.number = :invoicenumber";
    @Override
    @Transactional(propagation = Propagation.SUPPORTS)
    public Contract getInvoiceContract(final String invoiceNumber) {
        return (Contract) getHibernateTemplate().execute(new HibernateCallback() {
            public Object doInHibernate(Session session) throws HibernateException, SQLException {
                Query query = getSession().createQuery(INVOICE_CONTRACT);
                query.setString("invoicenumber", invoiceNumber);
                return query.uniqueResult();
            }
        });
    }

    @Override
    @Transactional(propagation = Propagation.SUPPORTS)
    public void save(Contract contract) {
        getHibernateTemplate().saveOrUpdate(contract);
    }

    private static final String ACTIVE_AT_DATE =
            "select contract from Contract contract where contract.validFrom <= :date and (contract.validUntil is null or contract.validUntil >= :date)";
    @Override
    @Transactional(propagation = Propagation.SUPPORTS)
    public List<Contract> getActiveContract(final Calendar cal) {
        return (List<Contract>) getHibernateTemplate().execute(new HibernateCallback() {
            public Object doInHibernate(Session session) throws HibernateException, SQLException {
                Query query = getSession().createQuery(ACTIVE_AT_DATE);
                query.setDate("date", cal.getTime());
                return query.list();
            }
        });
    }

    @Override
    public Contract getContract(String reference) {
        return getHibernateTemplate().get(Contract.class, reference);
    }
}
